﻿using System;
using System.Collections.Generic;
using SeaBattle.Domain.Abstract;
using SeaBattle.Domain.Entities;
using System.Linq;
using SeaBattle.Domain.Abstract.Services;

namespace SeaBattle.Domain.Concrete
{
    public class FakeGameRepository: IGameRepository
    {
        /// <summary>
        /// fake game storage to avoid GC affects
        /// </summary>
        private static List<Game> games = new List<Game>();
        private IPlayerService playerService;
        private IShipRepository shipRepository;
        private IFleetRepository fleetRepository;
        private IAccountService AccountService;
        private static bool Initialized = false;
        private static int CurrentGameID=6;

        public FakeGameRepository(IPlayerService playerService, IShipRepository shipRepository, IFleetRepository fleetRepository,IAccountService AccountService)
        {
            this.playerService = playerService;
            this.shipRepository = shipRepository;
            this.fleetRepository = fleetRepository;
            this.AccountService = AccountService;
            if (!Initialized)
                InitializeGames();
        }

        /// <summary>
        /// generates next id value upon the fake storage
        /// </summary>
        /// <returns>generated id value</returns>
        private int GetNextId()
        {
            return CurrentGameID++;
        }

        /// <summary>
        /// creates new game instance with creator player specified
        /// </summary>
        /// <param name="creator">creator player</param>
        /// <returns>created game instance</returns>
        public Game CreateNewGame(Player creator)
        {
            return new Game(GetNextId(), DateTime.Now, creator,shipRepository,fleetRepository);
        }

        /// <summary>
        /// save current game instance to the storage
        /// </summary>
        /// <param name="game">game instance</param>
        /// <returns>successful saving flag</returns>
        public bool SaveGame(Game game)
        {
            if (!games.Contains(game))
            {
                games.Add(game);
            }
            return true;
        }


        /// <summary>
        /// Loads the game.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public Game GetGame(int id)
        {
            return games.FirstOrDefault(x => x.Id == id);
        }

        public IEnumerable<Game> GetAllGames()
        {
            return from a in games select a;
        }

        private void InitializeGames()
        {
            games.Add(new Game(1, DateTime.Now, playerService.GetPlayer("vasya"),shipRepository,fleetRepository)
                { Preset = 100, Opened = true,Shot=new Shot(AccountService) });
            games.Add(new Game(2, DateTime.Now, playerService.GetPlayer("vasya"), shipRepository, fleetRepository) 
                { Preset = 200, Opened = true, Shot = new Shot(AccountService) });
            games.Add(new Game(3, DateTime.Now, playerService.GetPlayer("andrew"), shipRepository, fleetRepository) 
                { Preset = 300, Opened = true, Shot = new Shot(AccountService) });
            games.Add(new Game(4, DateTime.Now, playerService.GetPlayer("vasya"), shipRepository, fleetRepository) 
                { Preset = 400, Opened = true, Shot = new Shot(AccountService) });

            Game game = new Game(5, DateTime.Now, playerService.GetPlayer("vasya"), shipRepository, fleetRepository) 
                { Preset = 199, Opened = true, Shot = new Shot(AccountService) };
            game.JoinOpponent(playerService.GetPlayer("andrew"));
            string St = "1010101001101010100110101000001000000000000000000000000000011000000000000000000000000000001100100001";
            game.TryPrepareFleet(playerService.GetPlayer("vasya"), St);
            game.TryPrepareFleet(playerService.GetPlayer("andrew"), St);
            games.Add(game);
            
            CurrentGameID = 6;
            Initialized = true;
        }


        public void DeleteGame(int id)
        {
            for (int i = 0; i < games.Count; i++)
            {
                var x = games[i];
                if (x.Id == id)
                {
                    if (x.State == GameState.STATE_OPENED || x.State == GameState.STATE_CREATED)
                    {
                        AccountService.GetPlayerAccount(x.Creator.Login).AddAmount(x.Preset);
                        games.Remove(x);
                    }
                    else if (x.State == GameState.STATE_CLOSED)
                        games.Remove(x);
                }
            }
        }
    }
}
